
import netgravity.webservices.services.siteservices.SiteServiceServiceLocator;
import netgravity.webservices.services.siteservices.SiteServiceSoapBindingStub;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class ProbeTest {
  public static void main(String[] args) throws ClassNotFoundException {
    SiteServiceServiceLocator deSTELocator;
    SiteServiceSoapBindingStub deSTEService;

//    Class[] stubs = {SiteServiceSoapBindingStub.class, StyleServiceSoapBindingStub.class, SegmentationVariableServiceSoapBindingStub.class, OrderServiceSoapBindingStub.class, IndustryServiceSoapBindingStub.class, CreativeServiceSoapBindingStub.class, EventTypeServiceSoapBindingStub.class, MarketSegmentServiceSoapBindingStub.class, ProductServiceSoapBindingStub.class, SOAPMonitorServiceSoapBindingStub.class, FlightServiceSoapBindingStub.class, CurrencyTypeServiceSoapBindingStub.class, SiteServiceSoapBindingStub.class, AdSizeServiceSoapBindingStub.class, FrequencyCapGroupServiceSoapBindingStub.class, ExchangeRateServiceSoapBindingStub.class, ContactServiceSoapBindingStub.class, AffiliateServiceSoapBindingStub.class, AdvertiserServiceSoapBindingStub.class, AgencyServiceSoapBindingStub.class, AdServiceSoapBindingStub.class, RateCardServiceSoapBindingStub.class, MarketSegmentGroupServiceSoapBindingStub.class, PaymentTypeServiceSoapBindingStub.class, UserServiceSoapBindingStub.class};
      Class[] stubs = {SiteServiceSoapBindingStub.class};
      HashMap<Class, Class> classes = new HashMap();
      List<Class> asList = Arrays.asList(stubs);
      for (Class c : asList) {
        classes.put(c, ProbeTest.class);
      }

    for (Class stub : stubs) {
    
      HashMap<Class, Class> init = new HashMap<Class, Class>();
      init.put(stub, ProbeTest.class);
      
      HashMap<Class, Class> classmap = getClassesInvolved(init);

      System.out.println("All Involved types for : " + stub.getCanonicalName());
      for (Class c : classmap.keySet()) {
        System.out.println(c.getSimpleName() +  ": " + classmap.get(c).getSimpleName());
      }
      
      // All getters for these types
      for (Class c : classmap.keySet()) {
        if (! c.isPrimitive() && ! c.equals(String.class)) {

          Method[] declaredMethods = c.getDeclaredMethods();
          for (Method m : declaredMethods) {
            if (m.getName().contains("get") && ! Modifier.isStatic(m.getModifiers())) {
              System.out.println(" >> " + m.getName() + " : " + c.getSimpleName());
            }
          }
        }
      }
      
    }
    
    
    /* TODO write a sample hard-coded that converts
     * one WS Data Object to a GwtClient data object 
     * 
     * Adaptation:
     *      GwtAgencyData.getID() => AgencyData.getID();
     *      GwtAgencyData will have a field for getID() -- 
     *          when Gwt Client calls it, it will get same value as AgencyData.getID();
     *         problem is when GwtClient tries to -set- data using GwtAgencyData.setID()
     *         
     *      we'd have to make sure that when the object is going the other direction,
     *      the AgencyData.setID() is being set the same way.
     *      
     *      (ideas: add a layer of indirection?
     *      blah... hopefully we don't have to actually parse real java code)
     *     
     *      
     * Will generate each public method in AgencyData for GwtAgencyData
     * 
     * 
     */
  }
  
  /**
   * (only gets classes for Stubs)
   * @param classes to investigate
   * @return union of the classes and the new classes discovered and all further involved classes
   */
  public static HashMap<Class, Class> getClassesInvolved(HashMap<Class, Class> classes) {
    
    HashMap<Class, Class> classmap = new HashMap<Class, Class>();

    for (Class stub : classes.keySet()) {
      // get all methods
      try {
        
        // Only Add for Classes that belong to netgravity, java, or primitive
        String classname = stub.getCanonicalName();
        String simpleName = stub.getSimpleName();
        
        if (!stub.isPrimitive() && !classname.contains("axis") ) {
        
          Method[] methods = stub.getDeclaredMethods();
          
          // get all return types and fields in methods
          for (int j = 0; j < methods.length; j++  ) {
            int modifiers = methods[j].getModifiers();
            boolean isPub = Modifier.isPublic(modifiers);
            boolean isStatic = Modifier.isStatic(modifiers);
            
            // exclude constructors and private methods and static methods
            if (! methods[j].getName().equals(simpleName) && isPub && !isStatic) {
              System.out.println("               " + methods[j].getName());
              classmap.put(methods[j].getReturnType(), stub);
              Class[] parameterTypes = methods[j].getParameterTypes();
              for (int k = 0 ; k < parameterTypes.length; k++)
                classmap.put(parameterTypes[k], stub);
            }
          }
        }
      }
      
      catch (NoClassDefFoundError e) {
//        System.out.println(e.getMessage());
      }

    }

    classes.putAll(classmap);
    return classes;
//    if (classes.keySet().containsAll(classmap.keySet()))
//      return classes;
//    else {
//      classes.putAll(classmap);
//      return getClassesInvolved(classes);
//    }
  }
  
   
}
